package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.base.domain.User;
import cn.wolfcode.car.base.service.IUserService;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.CarPackageAuditMapper;
import cn.wolfcode.car.business.query.CarPackageAuditQuery;
import cn.wolfcode.car.business.query.CarPackageAuditQueryUp;
import cn.wolfcode.car.business.service.BpmnInfoService;
import cn.wolfcode.car.business.service.CarPackageAuditService;
import cn.wolfcode.car.business.service.ServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @Author WaveHi
 * @Date 17/11/2021 下午 2:59
 * @Version 1.0
 * @Contact HJBWaveHi@163.com
 * @Description
 */
@Service
public class CarPackageAuditServiceImpl extends ServiceImpl<CarPackageAuditMapper, CarPackageAudit> implements CarPackageAuditService {

//    @Autowired
//    private CarPackageAuditMapper carPackageAuditMapper;

    @Autowired
    private BpmnInfoService bpmnInfoService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ServiceItemService serviceItemService;

    @Autowired
    private IUserService userService;

    @Override
    public TablePageInfo<CarPackageAudit> getPartOfCarPackageAudits(CarPackageAuditQuery carPackageAuditQuery) {
        QueryWrapper<CarPackageAudit> carPackageAuditQueryWrapper = new QueryWrapper<>();
        carPackageAuditQueryWrapper
                .ge(carPackageAuditQuery.getBeginTime() != null,
                        "create_time",
                        carPackageAuditQuery.getBeginTime())
                .le(carPackageAuditQuery.getEndTime() != null,
                        "create_time",
                        carPackageAuditQuery.getEndTime());
        List<CarPackageAudit> list = list(carPackageAuditQueryWrapper);
        for (CarPackageAudit carPackageAudit : list) {
            carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
            carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
            carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
        }
        return new TablePageInfo<>(list);
//        return new TablePageInfo(carPackageAuditMapper.selectByCondition(carPackageAuditQuery));
    }

    @Override
    public Boolean add(CarPackageAudit carPackageAudit) {
        return save(carPackageAudit);
//        int insert = carPackageAuditMapper.insert(carPackageAudit);
//        return insert > 0;
    }

    @Override
    public Boolean update(CarPackageAudit carPackageAudit) {
        return updateById(carPackageAudit);
//        int i = carPackageAuditMapper.updateByPrimaryKey(carPackageAudit);
//        return i > 0;
    }

    @Override
    public InputStream getProcessImageByAuditId(Long id) {
        CarPackageAudit carPackageAudit = getById(id);
        carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
        carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
        carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
        BpmnInfo bpmnInfo = bpmnInfoService.getById(carPackageAudit.getBpmnInfoId());
//        CarPackageAudit carPackageAudit = this.getCarPackageAudit(id);
//        BpmnInfo bpmnInfo = bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId());
        InputStream inputStream=null;
        //如果状态为审核中或者审核拒绝，说明还正在流程中
        if(carPackageAudit.getStatus().equals(CarPackageAudit.STATUS_IN_ROGRESS) ){
            Task task = taskService.createTaskQuery().processInstanceId(carPackageAudit.getInstanceId()).singleResult();
            List<String> activeActivityIds = runtimeService.getActiveActivityIds(task.getExecutionId());

            inputStream = this.getProcessImage(bpmnInfo.getActProcessId(), activeActivityIds, Collections.EMPTY_LIST);
        }else{
            inputStream = this.getProcessImage(bpmnInfo.getActProcessId(), Collections.EMPTY_LIST,Collections.EMPTY_LIST);
        }

        return inputStream;
    }

    private InputStream getProcessImage(String actProcessId, List emptyList, List emptyList1) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(actProcessId);
        ProcessDiagramGenerator generator = new DefaultProcessDiagramGenerator();
        //generateDiagram(流程模型,需要高亮的节点,需要高亮的线条,后面三个参数都表示是字体)
        InputStream inputStream = generator.generateDiagram(bpmnModel, emptyList, emptyList1,
                "宋体","宋体","宋体");
        return inputStream;
    }

    @Override
    public CarPackageAudit getCarPackageAudit(Long id) {
        CarPackageAudit byId = getById(id);
        byId.setServiceItem(serviceItemService.getServiceItem(byId.getServiceItemId()));
        byId.setAuditor(userService.get(byId.getAuditorId()));
        byId.setBpmnInfo(bpmnInfoService.getBpmnInfo(byId.getBpmnInfoId()));
        return byId;
//        return carPackageAuditMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional
    public Boolean cancel(Long id) {
        //Get car package audit record
        CarPackageAudit carPackageAudit = getById(id);
        carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
        carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
        carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
//        CarPackageAudit carPackageAudit = carPackageAuditMapper.selectByPrimaryKey(id);
        //Set status of car package audit and service item
        carPackageAudit.setStatus(CarPackageAudit.STATUS_CANCEL);
        Boolean update01 = updateById(carPackageAudit);
        ServiceItem serviceItem = serviceItemService.getById(carPackageAudit.getServiceItemId());
        serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        Boolean update02 = serviceItemService.updateById(serviceItem);
//        int count = 0;
//        carPackageAudit.setStatus(CarPackageAudit.STATUS_CANCEL);
//        count += carPackageAuditMapper.updateByPrimaryKey(carPackageAudit);
//        Boolean update = serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_INIT);
        //Delete instance
        runtimeService.deleteProcessInstance(carPackageAudit.getInstanceId(), "审核取消");
        return  update01 || update02;
//        return count > 0 || update;
    }

    @Override
    public TablePageInfo<CarPackageAudit> getWork(Long id) {
        if(id != null) {
            QueryWrapper<CarPackageAudit> carPackageAuditQueryWrapper = new QueryWrapper<>();
            carPackageAuditQueryWrapper.eq("auditor_id", id);
            List<CarPackageAudit> list = list(carPackageAuditQueryWrapper);
            for (CarPackageAudit carPackageAudit : list) {
                carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
                carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
                carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
            }
            return new TablePageInfo<>(list);
//            return new TablePageInfo<>(carPackageAuditMapper.selectByAuditorId(id));
        }
        return new TablePageInfo<>(new ArrayList<>());
    }

    @Override
    public TablePageInfo<CarPackageAudit> getWork(CarPackageAuditQueryUp carPackageAuditQuery) {
        QueryWrapper<CarPackageAudit> carPackageAuditQueryWrapper = new QueryWrapper<>();
        carPackageAuditQueryWrapper
                .eq(carPackageAuditQuery.getAuditorId() != null,
                        "auditor_id",
                        carPackageAuditQuery.getAuditorId())
                .eq(carPackageAuditQuery.getStatus() != null,
                        "status",
                        carPackageAuditQuery.getStatus());
        List<CarPackageAudit> list = list(carPackageAuditQueryWrapper);
        for (CarPackageAudit carPackageAudit : list) {
            carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
            carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
            carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
        }
        return new TablePageInfo<>(list);
//        return new TablePageInfo<>(carPackageAuditMapper.selectByAuditorIdAndStatus(carPackageAuditQuery));
    }

    @Override
    @Transactional
    public void audit(Long id, Integer auditStatus, String info) {
        //Get car package audit
        CarPackageAudit carPackageAudit = getById(id);
        carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
        carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
        carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
//        CarPackageAudit carPackageAudit = this.getCarPackageAudit(id);
        ///Judge status of car package audit
        boolean incorrect = carPackageAudit == null || !CarPackageAudit.STATUS_IN_ROGRESS.equals(carPackageAudit.getStatus());
        if (incorrect) {
            throw new BusinessException("只能审批处理审批中状态的套餐审核！");
        }
        //Set info
        User user = ShiroUtils.getUser();
        boolean pass = CarPackageAudit.STATUS_PASS.equals(auditStatus);
        if(pass) {
            info = user.getUserName() + "同意审批:" + info;
        }else {
            info = user.getUserName() + "拒绝审批:" + info;

        }
        //Get task
        Task task = taskService.createTaskQuery()
                .processInstanceId(carPackageAudit.getInstanceId())
                .taskAssignee(user.getUserName())
                .singleResult();
        //Deal task
        carPackageAudit.setInfo(carPackageAudit.getInfo() + "<br>" + info);
        if(pass) {
            taskService.setVariable(task.getId(),"auditResult", true);
        }else {
            taskService.setVariable(task.getId(),"auditResult", false);

        }
        taskService.addComment(task.getId(), carPackageAudit.getInstanceId(), info);
        taskService.complete(task.getId());
        //Get next task
        Task nextTask = taskService.createTaskQuery()
                .processInstanceId(carPackageAudit.getInstanceId())
                .singleResult();
        //Judge next task
        if(pass) {
            if (nextTask == null) {
                //Change status of car package audit and service item
                if (pass) {
                    ServiceItem serviceItem = serviceItemService.getById(carPackageAudit.getServiceItemId());
                    serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_REPLY);
                    serviceItemService.updateById(serviceItem);
//                    serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_REPLY);
                    carPackageAudit.setStatus(CarPackageAudit.STATUS_PASS);
                } else {
                    ServiceItem serviceItem = serviceItemService.getById(carPackageAudit.getServiceItemId());
                    serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_APPROVED);
                    serviceItemService.updateById(serviceItem);
//                    serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_APPROVED);
                    carPackageAudit.setStatus(CarPackageAudit.STATUS_REJECT);
                }
            } else {
                carPackageAudit.setAuditorId(userService.queryByUserNameReal(nextTask.getAssignee()).getId());
                carPackageAudit.setAuditTime(new Date());
                carPackageAudit.setStatus(CarPackageAudit.STATUS_IN_ROGRESS);
            }
        } else {
            carPackageAudit.setStatus(CarPackageAudit.STATUS_REJECT);
            ServiceItem serviceItem = serviceItemService.getById(carPackageAudit.getServiceItemId());
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
            serviceItemService.updateById(serviceItem);
//            serviceItemService.changeAuditStatus(carPackageAudit.getServiceItemId(), ServiceItem.AUDITSTATUS_INIT);
        }
        updateById(carPackageAudit);
//        carPackageAuditMapper.updateByPrimaryKey(carPackageAudit);
    }

    @Override
    public TablePageInfo<CarPackageAudit> getWork(String userName) {
        QueryWrapper<CarPackageAudit> carPackageAuditQueryWrapper = new QueryWrapper<>();
        carPackageAuditQueryWrapper
                .like(userName != null,
                        "info",
                        userName);
        List<CarPackageAudit> list = list(carPackageAuditQueryWrapper);
        for (CarPackageAudit carPackageAudit : list) {
            carPackageAudit.setServiceItem(serviceItemService.getServiceItem(carPackageAudit.getServiceItemId()));
            carPackageAudit.setAuditor(userService.get(carPackageAudit.getAuditorId()));
            carPackageAudit.setBpmnInfo(bpmnInfoService.getBpmnInfo(carPackageAudit.getBpmnInfoId()));
        }
        return new TablePageInfo<>(list);
//        return new TablePageInfo<>(carPackageAuditMapper.selectByUserName(userName));
    }
}
